# -*- coding: utf-8 -*-
# @name             : 自定义断言
# @author           : OneYoung
# @create           : 2024/07/18
# @version          : v1.0
# @desc             : 封装常用的断言信息

import json
from utils.log_record import logger


class CustomAssert:

    def __init__(self, response):
        self.response = response

    def record_request_data(self):
        """记录请求数据"""
        # 记录body请求数据
        body = self.response.request.body
        try:
            body_data = body.decode(encoding='utf-8')  # byte转字符串
            json_loads = json.loads(body_data)
            if body_data != '{}':
                format_json = json.dumps(json_loads, indent=4, ensure_ascii=False)
                logger.info(f'request_body: {format_json}')
        except TypeError:
            logger.info(f'request_body: {body}')

    def response_normal(self):
        """断言响应信息是否正常"""
        try:
            status_code = self.response.status_code
            if 200 <= status_code <= 299:
                res_json = json.dumps(self.response.json(), indent=4, ensure_ascii=False)  # 可视化打印response
                logger.info(f"\n{self.response.url}\n{res_json}")  # 打印请求地址和响应数据
            elif 300 <= status_code <= 399:
                msg = f"断言失败，URL重定向 -> {status_code}."
                logger.error(msg)
                raise AssertionError(msg)
            elif 400 <= status_code <= 499:
                msg = f"断言失败，请求错误 -> {status_code}."
                logger.error(msg)
                raise AssertionError(msg)
            elif 500 <= status_code <= 599:
                msg = f"断言失败，服务器错误 -> {status_code}."
                logger.error(msg)
                raise AssertionError(msg)
            else:
                msg = f"断言失败，其他错误 -> {status_code}."
                logger.error(msg)
                raise AssertionError(msg)
        except AttributeError:
            msg = "断言失败，Response为空."
            logger.error(msg)
            raise AssertionError(msg)

    def status_code_equal(self, code: int = 200):
        """
        断言响应状态码是否与预期一致

        :param code: 状态码，默认200
        """
        status_code = self.response.status_code
        if status_code != code:
            msg = f"断言失败，status_code与预期不一致,预期:{code},实际:{status_code}."
            logger.error(msg, self.response.text)
            raise AssertionError(msg)

    def code_equal(self, code: int = 200):
        """
        断言错误状态码是否与预期一致

        :param code: 错误码，默认200
        """
        if self.response:
            response_json = json.loads(self.response.text)
            error_code = response_json.get('code')  # 错误状态码可根据实际场景更改，如：errorCode
            if error_code != code:
                msg = f"断言失败，错误状态码与预期不一致,预期:{code},实际:{error_code}."
                logger.error(msg)
                self.record_request_data()
                raise AssertionError(msg)

    def desc_equal(self, desc: str):
        """
        断言描述信息是否与预期一致

        :param desc: 描述信息
        """
        if self.response:
            response_json = self.response.json()
            r_desc = response_json.get('msg')  # 描述信息可根据实际场景更改，如：description
            if r_desc != desc:
                msg = f"断言失败，描述信息与预期不一致,预期:{desc},实际:{r_desc}."
                logger.error(msg)
                raise AssertionError(msg)

    def elapsed_time_less(self, elapsed: int):
        """
        断言响应时间是否小于预期值

        :param elapsed: 响应时间(s)
        """
        res_elapsed = self.response.elapsed.total_seconds()
        if res_elapsed > elapsed:
            msg = f"断言失败，响应时间大于预期时间,预期:{elapsed}(s),实际:{res_elapsed}(s)"
            logger.error(msg)
            raise AssertionError(msg)

    @staticmethod
    def data_equal(data, expected_data):
        """
        判断数据是否相等

        :param data: 需要对比的数据
        :param expected_data: 预期数据
        """
        if data != expected_data:
            msg = f"断言失败，数据不一致,预期:{expected_data},实际:{data}."
            logger.error(msg)
            raise AssertionError(msg)

    @staticmethod
    def data_not_equal(data, expected_data):
        """
        判断数据是否不等

        :param data: 返回结果
        :param expected_data: 预期结果
        """
        if data == expected_data:
            msg = f"断言失败，返回结果与预期结果一致."
            logger.error(msg)
            raise AssertionError(msg)

    @staticmethod
    def data_not_none(data):
        """
        断言数据不为空

        :param data: 断言数据
        """
        if not data:
            msg = "断言失败，数据为空."
            logger.error(msg)
            raise AssertionError(msg)

    @staticmethod
    def data_include(data, expected_data):
        """
        断言数据是否包含预期信息

        :param data: 断言信息
        :param expected_data: 预期信息
        """
        if expected_data not in data:
            msg = "断言失败，断言数据未包含预期信息."
            logger.error(msg)
            raise AssertionError(msg)
